local JewelSlot = require("app.public.dao.JewelSlot")

local Item = import(".Item")

local Equip = class("Equip",Item)

local ATTR_NUM = 3 -- 配置表中提供的一件装备最多属性条目数
local JEWEL_SLOT_NUM = 4 -- 配置表中提供的一件装备最多珠宝槽位数量

-- // 附加属性
-- message ExtraProp {
-- 	int32 index = 1;
-- 	int32 propID = 2;
-- 	int32 quality = 3;
-- 	int32 val = 4;
-- 	int32 posIdx = 5; //属性所在槽位索引
-- }

-- message Equipment {
-- 	string uid = 1;
-- 	int32 tid = 2;
-- 	bool isNew = 3;
-- 	int32 bind = 4;	// 0 - 未绑定, 1 - 已绑定
-- 	int32 location =5;//装备位置
-- 	repeated JewelSlot jewelSlots = 10; // 掉落宝石孔
-- 	repeated ExtraProp extraProps = 11; // 附加属性
-- 	int32 fashionID = 101; //时装id --现在存在EquipGrid里面
-- }

-- // 宝石孔
-- message JewelSlot {
-- 	Jewel jewel = 1;	// 宝石对象
-- 	//int32 unlockCond = 2; // 解锁条件,装备强化进度>=unlockCond
-- 	//int32 team  = 3;	// 宝石组(类型)
-- 	repeated int32 JewelType = 2; //宝石槽类型 要对应匹配的宝石
-- }

-- 构造一条额外属性的结构体
function Equip:ctorExtraProp( extraProp )
	local temp = {}
	if extraProp then
		-- temp.index = tonumber( extraProp.index or -1 ) -- 属性诞生时候所处的槽位索引？
		temp.propID = tonumber( extraProp.propID or -1 )
		temp.quality = tonumber( extraProp.quality or -1 )
		temp.val = tonumber( extraProp.val or -1 )
		temp.posIdx = tonumber( extraProp.posIdx or -1 )
	end
	return temp
end

function Equip:ctor(fromConf)
	Equip.super.ctor(self,Enums.ItemBagType.equip)

	self.bind = 0
	self.fashionID = nil -- 绑定的时装ID

	self.jewelSlots = nil
	self.extraProps = nil -- (额外属性)可转移属性列表

	self._isFromConf = fromConf or false -- 是否从配置表读取的数据，并没有详细属性
	self._isWear = false -- 是否穿戴
	self._hasExtraProps = false -- 是否含有(额外属性)可转移属性
end

function Equip:read(value)
	-- location ~= 0 表示穿身上装备
	-- ~= 0 时以服务器数据为准，为0时取配置表数据
	-- 两者区别可能就是配置表中 location = 7、9 的项可能跟格子不对应
	self.location = value.location or 0

	Equip.super.read( self, value )

	self.bind = value.bind
	-- TODO 装备时装id就是tid，后面需要读取EquipGrid里面数据
	self.fashionID = self.tid

	-- print("self.tid = ",self.tid)

	self.jewelSlots = {}
	for i = 1, JEWEL_SLOT_NUM do
		local jewelTyp = self[ "jewelTyp"..i ]

		if jewelTyp and "" ~= jewelTyp then
			local slot = JewelSlot.new( jewelTyp )
			if value.jewelSlots and value.jewelSlots[i] then
				slot:read( value.jewelSlots[i] )
			end
			table.insert( self.jewelSlots, slot )
		end
	end
	-- dump(self.jewelSlots,"self.jewelSlots",9)
	-- 水晶
	self._rockSlots = value.rockSlots or {}


	-- (额外属性)可转移属性列表
	self._hasExtraProps = false
	self.extraProps = {}
	if value.extraProps then
		for _,v in ipairs( value.extraProps ) do
			self._hasExtraProps = true
			table.insert( self.extraProps, self:ctorExtraProp( v ) )
		end
	end
	table.sort( self.extraProps,function(l,r)
		return l.posIdx < r.posIdx
	end)
end

function Equip:initDB()
	local conf = GD:getEquipConf(self.tid)
	local resConf = GD:getEquipResConf(self.tid)
	assert(conf ~= nil, "Equip.conf can't be nil")
    assert(resConf ~= nil, "Equip.resConf can't be nil")
    self.conf = conf
    self.resConf = resConf

    self.quality = tonumber(conf.quality or 1)
    self.location = 0 ~= self.location and self.location or tonumber(conf.location or 1)

    -- 使用等级，为了统一，名字和配置不一样
    self.useLv = tonumber(conf.lv or 1)
    self.bindType = tonumber(conf.bind or 0) -- 绑定类型
    self.gearScore = tonumber(conf.gearScore or 0) -- 装备评分

    -- 为了统一，转一次
    self.name = conf.string
    self.desc = conf.des

    -- 宝石孔类型
    for i = 1, 4 do
        self["jewelTyp"..i] = conf["jewelTyp"..i]
	end

    self._isInitAttr = false
    self._extraAttrNum = nil
end

function Equip:getIcon()
	if not self._icon then
		local icon = self.resConf and self.resConf.icon
		if icon and icon ~= "" then
			self._icon = string.format("%s%s.png", Res.weaponResPath, self.resConf.icon)
		else
			self._icon = Res.Sheep_Icon_Path
		end
	end
	return self._icon
end

function Equip:getIconBg()
	return Res.Qulity_Icon_Bg[self.quality]
end

function Equip:toJson()
	return json.encode( { uid = self.uid, tid = self.tid } )
end

function Equip:setWear(b)
	self._isWear = b
end

function Equip:isWear()
	return self._isWear
end

function Equip:getQuality()
	return self.quality
end

-- 写死的，需要和策划同步修改
function Equip:hasAvatar()
	local pos = self:getPos()
	if pos == 1 or pos == 2 or pos == 5 or pos == 6 or pos == 8 then
		return true
	elseif pos == 10 then
		-- 玩具，暂时也有avatar
		return true
	else
		return false
	end
end

-- 检测是否是适合职业的外显装备, classId 不填默认是自己的
-- return 是否可以，预览参数
function Equip:isClassAvatarEnable(classId)
	local able = self:hasAvatar() and self:isClassEnable(classId)
	return able, able and {type=1, id=self.tid} or nil
end

-- 返回装备部件pos
function Equip:getPos()
	return self.location
end

-- 使用者信息
function Equip:getUserShow()
	return L(self.conf.userShow)
end
-- 位置描述
function Equip:getPosName()
	return L(self.conf.locationtext)
end

-- 装备是否主武器
function Equip:isMainWeapon()
	return self:getPos() == 1
end

-- 获取类型名字，装备按位置显示名字
function Equip:getTypeName()
	return GD:getEquipPosName( self:getPos() )
end

-- 本装备是否成长型装备
function Equip:isAttrGrowthType()
	return "1" == self.conf.attrGrowth
end

-- 返回评分
function Equip:getGearScore()
	local gearScore = self.gearScore or 0
	if self:isAttrGrowthType() then -- 成长型装备？
		local conf = GD:getEquipRridEnhanceConfByStrengthenLevel( UD:getLevel() )
		local equipAttrPar = conf and tonumber( conf.equipAttrPar or 0)
		gearScore = math.floor( gearScore * equipAttrPar/10000 )
	end
	return gearScore
end

-- 返回使用等级
function Equip:getUseLv()
	return self.useLv
end

-- 返回珠宝槽位信息
function Equip:getAllSlots()
	return self.jewelSlots
end

--返回水晶槽内容
function Equip:getAllCrystalSlots()
	return self._rockSlots
end

--返回水晶槽数量
function Equip:getRockNum()
	return tonumber(self.conf.rockNum or 0)
end

--返回装备是否镶嵌了水晶
function Equip:isEquipHasCrystal()
	return #self._rockSlots > 0
end

--判断装备是否拥有紫色品质的词条
function Equip:isPreciousEquip()
	for k,v in ipairs(self.extraProps) do
		if v.quality >= Enums.AuctionFilterQuality.purple then
			return true
		end
	end
	return false
end

--道具的指导价
function Equip:getSuggestPrice()
	local isPrecious = self:isPreciousEquip()
	if isPrecious then
		return tonumber(self.conf.defaultPrice or 0)
	else
		return tonumber(self.conf.defaultPrice2 or 0)
	end
end

--道具的指导价
function Equip:getMaxSoldPrice()
	local isPrecious = self:isPreciousEquip()
	if isPrecious then
		return tonumber(self.conf.maxPrice or 0)
	else
		return tonumber(self.conf.maxPrice2 or 0)
	end
end


-- 返回宝石槽位类型
-- function Equip:getJewelSlotType( index )
-- 	return self["jewelTyp"..index]
-- end

-- 返回绑定的时装fashionID、对于不提供时装的装备可能是自身
function Equip:getFashionId()
	return self.fashionID
end

-- 装备本身提供的fashionId
function Equip:getProvideFashionId()
	return tonumber(self.conf.fashion or 0)
end

-- 装备默认的fashionId
function Equip:getDefaultFashionId()
	return tonumber(self.conf.fashionRes or 0)
end

-- 是否含有幻化信息
function Equip:isHaveIllusion()
	assert( self.fashionID, " ------------->>>>>>>>>>> 按照服务器的说法，装备的这个字段永远有值。没有幻化的话就为自身" )
	-- return self.fashionID ~= self:getDefaultFashionId()
	return false -- 功能似乎有修改，暂定false
end

-- 是否可以转移属性到身上装备
-- 获取属性格式 -- 
function Equip.getPorpFormat(porpId)
	if not Equip.propsFormatCache then
		local temp = {}
		for k,v in pairs( GD:getPropConfigs() ) do
			temp[tonumber(v.ID)] = tonumber(v.format) or 1
		end
		Equip.propsFormatCache = temp
	end
	return Equip.propsFormatCache[porpId] or 1
end

function Equip:canTransAttr()

	local flagTemp = false
	if self:_isHaveTransAttr() then -- 自身存在可以转移的属性
		local euqipOnPlayer = UD:getEquipByPos( self:getPos() )
		if euqipOnPlayer and 0 < euqipOnPlayer:getExtraAttrNum() and 0 < self:getExtraAttrNum() then -- 人物身上存在同部位装备？
			local playerEquips = {}
			for _ ,v in pairs(euqipOnPlayer.extraProps or {}) do
				local propID = tonumber( v.propID or 1 ) or 1
				local posIdx = tonumber( v.posIdx or -1 ) or -1
				local val = tonumber( v.val or -1 ) or -1
				local quality = tonumber( v.quality or 1 ) or 1
				if posIdx ~= -1 then
					playerEquips[posIdx] = {quality, val, propID}
				end
			end
			local isFind = false
			for _, v in pairs(self.extraProps or {}) do
				local propID = tonumber( v.propID or 1 ) or 1
				local posIdx = tonumber( v.posIdx or -1 ) or -1
				local val = tonumber( v.val or -1 ) or -1
				local quality = tonumber( v.quality or 1 ) or 1
				if posIdx ~= -1 then
					local playerEquip = playerEquips[posIdx]
					if playerEquip then
						-- 品质 相同 比较数值
						if quality == playerEquip[1] then
							-- 相同属性id
							if propID == playerEquip[3] then
								if val > playerEquip[2] then
									isFind = true
									break
								end
							else
								-- 不同属性id 默认 百分比的 比 数值的大
								local formatA = Equip.getPorpFormat(propID)
								local formatB = Equip.getPorpFormat(playerEquip[3])
								if formatA == formatB then
									if val > playerEquip[2] then
										isFind = true
										break
									end
								else
									if formatA > formatB then
										isFind = true
										break
									end
								end
							end
						else
							-- 品质 不同 高品质的推荐
							if quality > playerEquip[1] then
								isFind = true
								break
							end
						end
					else
						isFind = true
						break
					end
				end
			end
			flagTemp = isFind
		end
	end
	return flagTemp
end

-- 是否配置表中白板装备
function Equip:isFromConf()
	return self._isFromConf
end

-- 装备之后绑定，装备的时候添加提示
function Equip:needBindTip()
	return self.bind == 0 and self.conf.bind == "2"
end

-- 是否可以穿 1.符合职业 2.等级合适
function Equip:isCanEquip( lev )
	lev = lev or UD.player.level
	return self.useLv <= lev and self:isClassEnable()
end

-- 存在可转移的属性
function Equip:_isHaveTransAttr()
	return self._hasExtraProps or false
end

-- 检查输入的pos是否可以与本装备相互替换
-- 特殊逻辑：7／9 位置的装备可以相互替换
function Equip:isPosCanReplace(pos)
	local posTemp = self.location
	if posTemp == 7 or posTemp == 9 then
		return pos == 7 or pos == 9
	else
		return posTemp == pos
	end
end

-- 是否比身上装备更强力
function Equip:isBetterThanEquipOnPlayer()
	local posTemp = self:getPos()
	if 7 == posTemp or 9 == posTemp then -- 饰品
		local euqip_9_OnPlayer = UD:getEquipByPos( 9 )
		local euqip_7_OnPlayer = UD:getEquipByPos( 7 )
		if not euqip_7_OnPlayer or not euqip_9_OnPlayer then -- 任一一个为空
			return true
		elseif euqip_7_OnPlayer and euqip_9_OnPlayer then -- 两者皆不为空
			if euqip_7_OnPlayer:getGearScore() < self:getGearScore() or
				euqip_9_OnPlayer:getGearScore() < self:getGearScore() then
				return true
			end
		end
	else
		local euqipOnPlayer = UD:getEquipByPos( posTemp )
		if not euqipOnPlayer or euqipOnPlayer:getGearScore() < self:getGearScore() then
			return true
		end
	end
	return false
end

-- 强化等级
function Equip:getStrengthLv()
	return UD:getEquipGridStrengthByPos( self:getPos() ) or 0
end

-- 是否强化到当前能强化的最大等级
function Equip:isStrengthMax()
	-- TODO 强化等级上限 = 玩家等级 + 装备提升强化上限等级
	local tempVal = tonumber(GD:getSystemPar( "equipEnhanceMax"))
	local maxLv = math.min(tempVal, UD:getLevel() + tonumber(self.conf.enhanceAddLv))
	return self:getStrengthLv() >= maxLv
end

-- 是否可以继续强化
function Equip:canContinueStrength()
	local strengthenLevel = self:getStrengthLv() -- 当前强化等级

	local conf = GD:getEquipRridEnhanceConfByStrengthenLevel( strengthenLevel + 1 )
	if not self:isStrengthMax() then -- 等级没有超过玩家升级
		if conf and "" ~= conf["cost" .. self:getPos() ] then -- 存在下一级消耗
			local costItemList = UD:parseItemsFromString( conf["cost" .. self:getPos() ] )
			assert( 1 >= #costItemList, " -------------->>>>> 装备格子强化消耗多个物品？UI上只支持单消耗" )
			return UD:getItemAmountByTid( costItemList[1].tid ) >= costItemList[1].amount -- 消耗需求物品数量足够？
		else
			return false
		end
	end
	return false
end

-- 是否可以镶嵌宝石
function Equip:canSetJewel()
	return #self.jewelSlots > 0
end

function Equip:isEquipHasJewel()
	for k, v in pairs(self.jewelSlots) do
		if v:hasJewel() then
			return true
		end
	end
	return false
end

-- 获取套装id
function Equip:getSuit()
	return self.conf.suit
end

-- 获取附带技能增益
function Equip:getClassSkill()
	return self.conf.classSkillID
end

-- 附加属性条目数
function Equip:getExtraAttrNum()
	if not self._extraAttrNum then
		self._extraAttrNum = tonumber(self.conf.extraAttrNum or 0)
	end
	return self._extraAttrNum
end

-- 获取来源
function Equip:getResource()
	-- subMenu 用于拍卖行跳转
	local resource = GD:getConvertResource(self.conf.getResource, Enums.ItemBagType.equip, tonumber(self.conf.ID), self:getSubMenu())
	return resource
end
------------------------------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 一件装备的属性相关
-- 强化加成提供的属性
function Equip:getStrengthAttr( strengthenLv )
	if not self._isInitAttr then
		-- 属性相关
		local conf = self.conf
		for i = 1, 3 do
			self["attrType"..i] = tonumber(conf["attrType"..i])
			self["attrVal"..i] = tonumber(conf["attrVal"..i])
			self["enhancePar"..i] = tonumber(conf["enhancePar"..i]) or 0
		end
		self._isInitAttr = true
	end

	strengthenLv = strengthenLv or self:getStrengthLv()

	local curStrengthenLevelEquipRridEnhanceConf = GD:getEquipRridEnhanceConfByStrengthenLevel( strengthenLv )
	local strengthenCoefficient = curStrengthenLevelEquipRridEnhanceConf and tonumber( curStrengthenLevelEquipRridEnhanceConf.par ) or 0

	local curLevelGrowthConf = GD:getEquipRridEnhanceConfByStrengthenLevel( UD:getLevel() )
	local growthCoefficient = curLevelGrowthConf and tonumber( curLevelGrowthConf.equipAttrPar ) or 0
	local attrTemp = {}
	for i = 1, ATTR_NUM do
		if self["attrType"..i] then -- 提供了属性
			local baseAttr = self["attrVal"..i]
			if self:isAttrGrowthType() then -- 成长型装备？
				baseAttr = baseAttr * growthCoefficient/10000
			end
			attrTemp[ self["attrType"..i] ] = baseAttr + strengthenCoefficient / 10000 * self["enhancePar"..i]
		end
	end
	-- dump( attrTemp, " -------->>>>>>>>>>>> 装备的强化加成之后属性 " )
	return attrTemp
end

-- (额外属性)可转移属性
function Equip:getExtraAttr()
	local attrTemp = {}
	for i,v in ipairs( self.extraProps ) do
		attrTemp[ v.propID ] = tonumber( v.val )
	end
	-- dump( attrTemp, " -------->>>>>>>>>>>> 装备的额外属性 " )
	return attrTemp
end

-- 单条额外属性的品质
function Equip:getExtraAttrQualityByPropid( propID )
	local extraAttrQuality = 1
	for i,v in ipairs( self.extraProps ) do
		if v.propID == tonumber( propID ) then
			extraAttrQuality = v.quality
			break
		end
	end
	return extraAttrQuality
end

-- 珠宝提供的属性
function Equip:getJewelAttr()
	local jewlAttrTemp = {}
	for i,v in ipairs( self.jewelSlots ) do
		if v:hasJewel() then
			local attrId = v.jewel:getAttrType()
			local attrVal = v.jewel:getAttrVal()

			if jewlAttrTemp[attrId] then
				jewlAttrTemp[attrId] = jewlAttrTemp[attrId] + attrVal
			else
				jewlAttrTemp[attrId] = attrVal
			end
		end
	end
	return jewlAttrTemp
end

-- 装备提供的总属性：强化加成(包含裸的) and 珠宝加成
function Equip:getTotalAttr( strengthenLv )
	local strengthAttr = self:getStrengthAttr( strengthenLv )
	local extraAttr = self:getExtraAttr()
	local jewelAttr = self:getJewelAttr()

	local equipAttrListTemp = {}
	for k,v in pairs( strengthAttr ) do
		UD:MergeAttr( equipAttrListTemp, { k, v } )
	end
	for k,v in pairs( extraAttr ) do
		UD:MergeAttr( equipAttrListTemp, { k, v } )
	end
	for k,v in pairs( jewelAttr ) do
		UD:MergeAttr( equipAttrListTemp, { k, v } )
	end

	-- dump( equipAttrListTemp, " ------------------>>>>>> getTotalAttr " .. tostring( self.tid ) )

	return equipAttrListTemp
end

-- 该槽位是否有附加属性
function Equip:isHaveExtraAttrByPos(posIdx)
	for i, v in ipairs(self.extraProps) do
		if posIdx == v.posIdx then
			return true
		end
	end
	return false
end

-- 根据槽位获取该槽位上的附加属性ID
function Equip:getExtraAttrIdByPos(posIdx)
	local id
	local extraAttr = self.conf["extraAttr"..posIdx]
	if extraAttr then
		local temp = string.splitTwice(extraAttr, {";", "|"}, true)
		for i, v in ipairs(temp) do
			local propConf = GD:getPropConfig(v[1])
			if propConf and propConf.format == "2" then
				id = v[1]
				break
			end
		end
	end
	return id
end

return Equip
